<template>
  <div>
    <el-card class="box-card" style="margin-bottom:10px;position:relative;">
      <el-button :disabled="isRefreshing" size="mini" @click="actionRefresh" class="btn-refresh">刷新</el-button>
      <el-breadcrumb separator="/">
        <el-breadcrumb-item class="path-item" @click.native="actionGoToRoot()">Root</el-breadcrumb-item>
        <el-breadcrumb-item class="path-item" v-for="(pathpart,index) in path" :key="pathpart" 
          @click.native="actionGoToByPathPartIndex(index)"
        >{{pathpart}}</el-breadcrumb-item>
      </el-breadcrumb>
    </el-card>

    <el-card class="box-card">
      <el-table :data="fileSorted" size="mini">
        <el-table-column label="类型" width="80">
          <template slot-scope="scope">
            <i v-if="scope.row.type == 'd'" class="el-icon-folder"></i>
            <i v-if="scope.row.type == '-'" class="el-icon-document"></i>
          </template>
        </el-table-column>
        <el-table-column label="文件名" width="180">
          <template slot-scope="scope">
            <el-button type="text" :disabled="'d' != scope.row.type" 
              @click="actionGoToName(scope.row.name)"
            >{{scope.row.name}}</el-button>
          </template>
        </el-table-column>
        <el-table-column label="大小" width="180">
          <template slot-scope="scope">
            {{scope.row.size | filesize }}
          </template>
        </el-table-column>
        <el-table-column label="使用量" width="250">
          <template slot-scope="scope">
            <el-progress :text-inside="true" :stroke-width="20" :percentage="getUsagePercentage(scope.row.size)"></el-progress>
          </template>
        </el-table-column>
        <el-table-column label="" width="50">
          <template slot-scope="scope">
            <i v-if="'wait' == scope.row.status" class="el-icon-time"></i>
            <i v-if="'calculating' == scope.row.status" class="el-icon-loading"></i>
          </template>
        </el-table-column>
        <el-table-column>
          <template slot-scope="scope">
            <div style="text-align:right;">
              <el-button size="mini" @click="actionFileDelete(scope.row)">删除</el-button>
            </div>
          </template>
        </el-table-column>
    </el-table>
    </el-card>
  </div>
</template>
<script>
import Formatter from '../../utils/Formatter.js'
import Common from '../../utils/Common.js'
import RegexMatch from '../../utils/RegexMatch.js'
export default {
    data() {
        return {
            path : [],
            curCalCmd : null,
            isRefreshing : false,
            stopSizeCal : 'no',
            totalSize : 0,
            files : []
        };
    },
    async mounted() {
        await this.refresh();
    },
    computed : {
        fileSorted() {
            let status = ['done', 'wait', 'calculating'];
            let files = this.files.slice();
            files.sort(( fileA, fileB ) => {
                if ( fileA.status == fileB.status ) {
                    return fileB.size - fileA.size;
                } else {
                    return status.indexOf(fileB.status) - status.indexOf(fileA.status);
                }
            });
            return files;
        },
    },
    filters : {
        filesize ( value ) {
            return Formatter.asFileSize(value);
        },
    },
    methods : {
        /** */
        async actionFileDelete( file ) {
            try {
                let typename = 'd' == file.type ? '目录' : '文件';
                await this.$confirm(`此操作将删除该${typename}, 是否继续?`, '提示', {
                    confirmButtonText: '确定',
                    cancelButtonText: '取消',
                    type: 'warning'
                });
            } catch {
                return;
            }

            let path = null;
            if ( 0 == this.path.length ) {
                path = '/' + file.name;
            } else {
                path = '/' + this.path.join('/') + '/' + file.name;
            }
            let flag = 'd' == file.type ? 'r' : '';
            let cmd = `rm -f${flag} ${path}`;
            
            let server = this.$store.getters.serverCurrent;
            let client = await server.getSshClient();
            await client.exec(cmd);
            this.totalSize -= file.size;
            for ( let i=0; i<this.files.length; i++ ) {
                if ( file.type == this.files[i].type && file.name == this.files[i].name ) {
                    this.files.splice(i,1);
                }
            }
        },
        /** */
        async actionRefresh() {
            await this.refresh();
        },
        /** */
        async actionGoToByPathPartIndex(index) {
            let path = [];
            for ( let i=0; i<=index; i++ ) {
                path.push(this.path[i]);
            }
            path = '/' + path.join('/');
            await this.gotoPath(path);
        },
        /** */
        async actionGoToRoot() {
            await this.gotoPath('/');
        },
        async actionGoToName(name) {
            let path = null;
            if ( 0 == this.path.length ) {
                path = '/' + name;
            } else {
                path = '/' + this.path.join('/') + '/' + name;
            }
            await this.gotoPath(path);
        },
        /** */
        async gotoPath( path ) {
            await this.stopCurrentSizeCal();
            if ( '/' == path ) {
                this.path = [];
            } else {
                this.path = path.substring(1).split('/');
            }
            await this.refresh();
        },
        /** */
        async refresh() {
            this.isRefreshing = true;
            
            let path = '/' + this.path.join('/');
            let server = this.$store.getters.serverCurrent;
            let client = await server.getSshClient();
            let ls = await client.exec(`ls -al --time-style '+%Y-%m-%d %H:%M:%S' --color=never ${path}`);
            ls = ls.trim().split('\r\n');
            ls.shift(); ls.shift(); ls.shift();

            this.totalSize = 0;
            this.files = [];
            let lsRegex = /^(?<type>.)\S+\s+\d+\s+(?<owner>\S+)\s+(?<group>\S+)\s+(?<size>\d+)\s+(?<time>.*?:\d+)\s+(?<name>.*?)$/;
            for ( let i=0; i<ls.length; i++ ){
                let lsMatch = ls[i].match(lsRegex);
                if ( null == lsMatch ) {
                    debugger;
                }
                let file = lsMatch.groups;
                file.status = 'done';
                if ( 'd' == file.type ) {
                    file.size = 0;
                    file.status = 'wait';
                }
                file.usage = 0;
                this.files.push(file);
                this.totalSize += file.size*1;
            }

            await this.calculateFilesSize();
            this.isRefreshing = false;
        },

        /** 计算文件尺寸 */
        async calculateFilesSize() {
            let server = this.$store.getters.serverCurrent;
            let client = await server.getSshClient();
            let path = '/' + this.path.join('/');
            this.$forceUpdate();
            for ( let i=0; i<this.files.length; i++ ) {
                if ( this.stopSizeCal == 'yes' ) {
                    this.stopSizeCal = 'done';
                    break;
                }
                
                if ( 'wait' != this.files[i].status ) {
                    continue;
                }

                this.files[i].status = 'calculating';
                this.$forceUpdate();
                
                let filepath = ('/' == path ? '' : path ) + '/' + this.files[i].name;
                let cmd = `du -b --max-depth=0 ${filepath} 2>/dev/null`;
                this.curCalCmd = cmd;
                let size = await client.exec(cmd);
                size = size.trim();
                if ( '' == size ) {
                    continue;
                }

                console.log('calculating : ' + size);
                this.files[i].size = size.trim().split('\t')[0] * 1;
                this.totalSize += this.files[i].size;
                this.files[i].status = 'done';
                console.log(`${cmd} done`);
                this.$forceUpdate();
                this.curCalCmd = null;
            }

            this.$forceUpdate();
        },

        /** */
        getUsagePercentage( size ) {
            let total = 0 == this.totalSize ? 1 : this.totalSize;
            let usage = (size / total * 100).toFixed(2);
            if ( usage > 100 ) {
                usage = 100;
            }
            usage = parseFloat(usage);
            return usage;
        },
        /** */
        async stopCurrentSizeCal() {
            let loading = this.$loading({fullscreen: true});
            if ( !this.isRefreshing ) {
                loading.close();
                return;
            }

            console.log('stop size cal : start');
            this.stopSizeCal = 'yes';

            let server = this.$store.getters.serverCurrent;
            let client = await server.getSshClient();
            let psCmd = `ps -aux | grep "${this.curCalCmd}" | grep -v " grep "`;
            let ps = await client.exec(psCmd);
            let psMatch = RegexMatch.match('ps-aux', ps);
            if ( null != psMatch ) {
                await client.exec(`kill -9 ${psMatch.pid}`);
            }

            while ( true ) {
                console.log('stop size cal : check');
                if ( 'done' != this.stopSizeCal || this.isRefreshing ) {
                    Common.msleep(100);
                }

                console.log('stop size cal : done');
                this.stopSizeCal = 'no';
                loading.close();
                break;
            }
        }
    },
}
</script>
<style scoped>
.path-item {cursor:pointer;}
.btn-refresh {position: absolute;right: 13px;bottom: 13px;}
</style>